package org.jdsm.flow.core.users;

import java.util.Set;

/**
 * User: Mykhaylo Komarichyn
 * Date: 10.06.2010
 * Time: 18:14:10
 */
public interface IUserService {




    /**
     * load user entity. param user have to contains id property. {@link org.jdsm.flow.core.base.IEntity}
     * method will return null if user can't be found by id property
     *
     * @param user user object not contain all data
     * @return null if can't found user
     */
    public IUser loadUser(IUser user);

    /**
     * {@link org.jdsm.flow.core.users.dao.IUserDao#findUserRolesByUserId}
     *
     * @param user user entity. it has to has id property{@link org.jdsm.flow.core.base.IEntity}
     * @return user roles or empty set
     */
    public Set<IRole> findUserRoles(IUser user);


    /**
     * {@link org.jdsm.flow.core.users.dao.IUserDao#findUserGroupsByUserId}
     *
     * @param user entity. it has to has id property {@link org.jdsm.flow.core.base.IEntity}
     * @return user groups or empty set
     */
    public Set<IGroup> findUserGroups(IUser user);

    /**
     * load role entity. param role have to contains id property. {@link org.jdsm.flow.core.base.IEntity}
     * method will return null if role can't be found by id property
     *
     * @param role role entity
     * @return null if can't found role
     */
    public IRole loadRole(IRole role);

    /**
     * load all users which has access to role. If no user found method returns empty set
     *
     * @param role role object
     * @return list of users {@link IUser} or empty list
     */
    public Set<IUser> findUsersForRole(IRole role);

    /**
     * if current role has permission = 10 then allowed roles must to has permission < 10
     *
     * @param role role object
     * @return list of allowed roles or empty list
     */
    public Set<IRole> findAllowedRoles(IRole role);

    /**
     * load group entity. param group have to contains id property. {@link org.jdsm.flow.core.base.IEntity}
     * method will return null if user can't be found by id property
     *
     * @param group group object
     * @return founded group or null if can't found
     */
    public IGroup loadGroup(IGroup group);

    /**
     * load all users which has access to group. If no user found method returns empty set
     *
     * @param group group object
     * @return list of users {@link IUser} or empty list
     */
    public Set<IUser> findUsersForGroup(IGroup group);

    /**
     * if current group has permission = 30 then allowed groups must to has permission < 30
     *
     * @param group group object
     * @return list of allowed groups or empty list
     */
    public Set<IGroup> findAllowedGroups(IGroup group);

    /**
     * load users entities by criteria
     *
     * @param maxResult   limit return result
     * @param startResult start value from result
     * @param isSort      is sort result by field
     * @param field       field for sorting result
     * @return list of users or empty list
     */
    public Set<IUser> loadUsersByCriteria(int maxResult, int startResult, boolean isSort, String field);

    /**
     * load groups entities by criteria
     *
     * @param maxResult   limit return result
     * @param startResult start value from result
     * @param isSort      is sort result by field
     * @param field       field for sorting result
     * @return list of groups or empty list
     */
    public Set<IGroup> loadGroupsByCriteria(int maxResult, int startResult, boolean isSort, String field);

    /**
     * load roles entities by criteria
     *
     * @param maxResult   limit return result
     * @param startResult start value from result
     * @param isSort      is sort result by field
     * @param field       field for sorting result
     * @return list of roles or empty list
     */
    public Set<IRole> loadRolesByCriteria(int maxResult, int startResult, boolean isSort, String field);

    /**
     * delete user
     *
     * @param user user
     */
    public void removeUser(IUser user);

    /**
     * delete role
     *
     * @param role role
     */
    public void removeRole(IRole role);

    /**
     * delete group
     *
     * @param group group
     */
    public void removeGroup(IGroup group);

    /**
     * include user to role or add user permission
     *
     * @param user user
     * @param role role
     */
    public void includeUser(IUser user, IRole role);

    /**
     * include user to group
     *
     * @param user  user
     * @param group group
     */
    public void includeUser(IUser user, IGroup group);

    /**
     * cascades operation {@link #includeUser(IUser, IRole)}
     *
     * @param user  user entity
     * @param roles set of roles for for including user to this one
     */
    public void includeUserToRoles(IUser user, Set<IRole> roles);

    /**
     * cascades operation {@link #includeUser(IUser, IGroup)}
     *
     * @param user   user entity
     * @param groups set of groups for for including user to this one
     */
    public void includeUserToGroups(IUser user, Set<IGroup> groups);

    /**
     * exclude user from role or take away user permission
     *
     * @param user user
     * @param role role
     */
    public void excludeUser(IUser user, IRole role);

    /**
     * exclude user from group
     *
     * @param user  user
     * @param group group
     */
    public void excludeUser(IUser user, IGroup group);

    /**
     * cascades operation {@link #excludeUser(IUser, IRole)}
     *
     * @param user  user entity
     * @param roles set of roles for excluding user
     */
    public void excludeUserFromRoles(IUser user, Set<IRole> roles);

    /**
     * cascades operation {@link #excludeUser(IUser, IGroup)}
     *
     * @param user   user entity
     * @param groups set of groups for excluding user
     */
    public void excludeUserFromGroups(IUser user, Set<IGroup> groups);


    /**
     * save or update user entity
     *
     * @param user user
     * @return saved user or null if user object can't was saved
     */
    public IUser saveOrUpdate(IUser user);

    /**
     * save or update role entity
     *
     * @param role role
     * @return saved role or null if role object can't was saved
     */
    public IRole saveOrUpdate(IRole role);

    /**
     * save or update group  entity
     *
     * @param group group
     * @return saved group or null if group object can't was saved
     */
    public IGroup saveOrUpdate(IGroup group);

    /**
     * if permission < than permission of groups in db, return value will be empty list
     *
     * @param permission permission
     * @return list of group or empty list
     */
    public Set<IGroup> loadAllowedGroupsByPermission(Long permission);

    /**
     * * if permission < than permission of groups in db, return value will be empty list
     *
     * @param permission permission
     * @return list of role or empty list
     */
    public Set<IRole> loadAllowedRolesByPermission(Long permission);

    /**
     * can user access to group
     *
     * @param user  user
     * @param group group
     * @return true if user has access to group
     */
    public boolean isAllowedUserAccess(IUser user, IGroup group);

    /**
     * can user access to role
     *
     * @param user user
     * @param role role
     * @return true if user has access to role
     */
    public boolean isAllowedUserAccess(IUser user, IRole role);

    /**
     * find user entity by name {@link org.jdsm.flow.core.users.IUser#getName()}
     *
     * @param name user name
     * @return user {@link IUser}
     */
    public IUser findUserByName(String name);

    /**
     * find user entity by nickname {@link org.jdsm.flow.core.users.IUser#getNickName()}
     *
     * @param nickName user nick name
     * @return user {@link IUser}
     */
    public IUser findUserByNickName(String nickName);

    /**
     * find role entity by name {@link org.jdsm.flow.core.users.IRole#getName()}
     *
     * @param name role name
     * @return role {@link IRole}
     */
    public IRole findRoleByName(String name);

    /**
     * find group entity by name {@link org.jdsm.flow.core.users.IGroup#getName()}
     *
     * @param name group name
     * @return group {@link IGroup}
     */
    public IGroup findGroupByName(String name);

    /**
     * find roles with permission < of permission as param
     *
     * @param permission permission
     * @return list of roles
     */
    public Set<IRole> findRolesByPermission(Long permission);

    /**
     * find groups with permission < of permission as param
     *
     * @param permission permission
     * @return list of group
     */
    public Set<IGroup> findGroupsByPermission(Long permission);

    /**
     * change user roles
     *
     * @param user  user entity
     * @param roles new user roles
     */
    void reassignUserRoles(IUser user, Set<IRole> roles);

    /**
     * change user group
     *
     * @param user   user entity
     * @param groups set of new user group
     */
    void reassignUserGroups(IUser user, Set<IGroup> groups);

    /**
     * @return count of users
     */
    public int usersCount();

    /**
     * @return count of roles
     */
    public int rolesCount();

    /**
     * @return count of groups
     */
    public int groupCount();

    /**
     * //todo add javadoc
     *
     * @param user
     * @param rolesName
     * @return
     */
    boolean hasUserAccessToRolesByName(IUser user, Set<String> rolesName);

    /**
     * //todo add javadoc
     *
     * @param user
     * @param roles
     * @return
     */
    boolean hasUserAccessToRoles(IUser user, Set<IRole> roles);

    /**
     * //todo add javadoc
     *
     * @param user
     * @param groupsName
     * @return
     */
    boolean hasUserAccessToGroupByName(IUser user, Set<String> groupsName);

    /**
     * //todo add javadoc
     *
     * @param user
     * @param groups
     * @return
     */
    boolean hasUserAccessToGroups(IUser user, Set<IGroup> groups);

    /**
     * @return blank user entity
     */
    public IUser newUserInstance();

    /**
     * @return blank group entity
     */
    public IGroup newGroupInstance();

    /**
     * @return blank role entity
     */
    public IRole newRoleInstance();
    public IRole newRoleInstance(String roleName, Long permission);
    public IGroup newGroupInstance(String groupName, Long permission);

    boolean hasUserAccess(IUser user, Set<String> roleNames, Set<String> groupsName);

    void setUserName(IUser user, String newUserName);
    void setPassword(IUser user, String password);
    void setHint(IUser user, String hint);
    void setNickName(IUser user, String nickName);
}
